-module(mutex_v2).
-export([start/0, stop/0]).
-export([wait/0, signal/0]).
-export([init/0]).

start() ->
    register(mutex, spawn(?MODULE, init, [])).

stop() ->
    mutex ! stop.

wait() ->
    mutex ! {wait, self()},
    receive ok -> ok end.
	    
signal() ->
    mutex ! {signal, self()}, ok.
     
init() ->
    free().

free() ->
    receive
	{wait, Pid} ->
	    io:format("monitoring ~p~n", [Pid]),
	    Ref = erlang:monitor(process, Pid),
	    Pid ! ok,
	    busy(Pid, Ref);
	stop ->
	    terminate()
    end.

busy(Pid, Ref) ->
    receive
	{signal, Pid} ->
	    io:format("signal from/demonitoring ~p~n", [Pid]),
	    erlang:demonitor(Ref),
	    free();
	{'DOWN', _Reference, process, Pid, _Reason} ->
	    io:format("waitting processes dies ~p~n", [Pid]),
	    free()
    end.

terminate() ->
    receive
	{wait, Pid} ->
	    exit(Pid, kill),
	    terminate()
    after
	0 -> ok
    end.
